package com.micro.platform.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.micro.platform.user.controller.function.FunctionDeletedRequ;
import com.micro.platform.user.controller.function.FunctionEditedRequ;
import com.micro.platform.user.controller.function.FunctionInfosResp;
import com.micro.platform.user.controller.function.FunctionNewRequ;
import com.micro.platform.user.controller.functionapi.FunctionApiNewRequ;
import com.micro.platform.starter.utils.AssertUtil;
import com.micro.platform.starter.utils.BeanCopyUtil;
import com.micro.platform.user.entity.Function;
import com.micro.platform.user.entity.FunctionApi;
import com.micro.platform.user.entity.Menu;
import com.micro.platform.user.mapper.FunctionMapper;
import com.micro.platform.user.service.FunctionApiService;
import com.micro.platform.user.service.FunctionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.platform.user.service.MenuService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户-功能表 服务实现类
 * </p>
 *
 * @author zhouyk
 * @since 2021-12-06
 */
@Service
public class FunctionServiceImpl extends ServiceImpl<FunctionMapper, Function> implements FunctionService {

    @Autowired
    private MenuService menuService;

    @Autowired private FunctionApiService functionApiService;

    @Override
    public Boolean addFunction(FunctionNewRequ functionNewRequ) {
        Menu menu = menuService.getById(functionNewRequ.getMenuId());
        AssertUtil.notIsNull(menu, "您选择的菜单无效");
        QueryWrapper<Function> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Function::getName, functionNewRequ.getName())
                .eq(Function::getDeleted, Boolean.FALSE);
        int count = count(queryWrapper);
        AssertUtil.isFalse(count > 0, "功能名称已存在");
        Function function = BeanCopyUtil.copyProperties(functionNewRequ, Function::new);
        boolean save = save(function);
        List<FunctionApiNewRequ> functionApiNewRequs = functionNewRequ.getFunctionApiNewRequs();
        if(CollectionUtils.isNotEmpty(functionApiNewRequs)){
            Long id = function.getId();
            for (FunctionApiNewRequ apiNewRequs : functionApiNewRequs) {
                apiNewRequs.setFunctionId(id);
            }
            functionApiService.addBatchFunctionApi(functionApiNewRequs, id);
        }
        return save;
    }

    @Override
    public List<FunctionInfosResp> listAll(String platformCode) {
        QueryWrapper<Function> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<Function> functionLambdaQueryWrapper = queryWrapper.lambda().eq(Function::getDeleted, Boolean.FALSE);
        if(StringUtils.isNotEmpty(platformCode)){
            functionLambdaQueryWrapper.eq(Function::getPlatformCode, platformCode);
        }
        List<Function> list = list(queryWrapper);
        List<FunctionInfosResp> listFunctions = BeanCopyUtil.copyListProperties(list, FunctionInfosResp::new);
        if(listFunctions == null){
            return Collections.emptyList();
        }
        return listFunctions;
    }

    @Override
    public List<FunctionInfosResp> listByMenuId(Long menuId, String platformCode) {
        List<Menu> menus = menuService.getMenuTreeNodesById(menuId, platformCode);
        if(CollectionUtils.isEmpty(menus)){
            return Collections.EMPTY_LIST;
        }
        Map<Long, Menu> mapId2Menu = menus.stream().collect(Collectors.toMap(Menu::getId, java.util.function.Function.identity()));
        QueryWrapper<Function> functionQueryWrapper = new QueryWrapper<>();
        functionQueryWrapper.lambda().eq(Function::getDeleted, Boolean.FALSE).eq(Function::getPlatformCode, platformCode).in(Function::getMenuId, menus.stream().map(Menu::getId).collect(Collectors.toList()));
        List<Function> list = list(functionQueryWrapper);
        List<FunctionInfosResp> listFunctions = BeanCopyUtil.copyListProperties(list, FunctionInfosResp::new);
        if(listFunctions == null){
            return Collections.emptyList();
        }
        List<Long> functionIds = listFunctions.stream().map(FunctionInfosResp::getId).collect(Collectors.toList());
        List<FunctionApi> functionApis = functionApiService.getFunctionApisByFunctionIds(functionIds);
        Map<Long, List<FunctionApi>> mapId2FunctionApi = functionApis.stream().collect(Collectors.groupingBy(FunctionApi::getFunctionId, Collectors.toList()));
        listFunctions.forEach(functions -> {
            List<FunctionApi> functionApis1 = mapId2FunctionApi.get(functions.getId());
            if(functionApis1 == null){
                functionApis1 = new ArrayList<>();
            }
            functions.setFunctionApis(functionApis1);
            functions.setMenuName(mapId2Menu.get(functions.getMenuId()).getTitle());
        });
        return listFunctions;
    }

    @Override
    public Boolean edited(FunctionEditedRequ functionEditedRequ) {
        Function function = BeanCopyUtil.copyProperties(functionEditedRequ, Function::new);
        boolean update = updateById(function);
        List<FunctionApiNewRequ> functionApiNewRequs = functionEditedRequ.getFunctionApiNewRequs();
        if(update && CollectionUtils.isNotEmpty(functionApiNewRequs)){
            Long id = functionEditedRequ.getId();
            for (FunctionApiNewRequ apiNewRequs : functionApiNewRequs) {
                apiNewRequs.setFunctionId(id);
            }
            functionApiService.addBatchFunctionApi(functionApiNewRequs, id);
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean deleted(FunctionDeletedRequ functionDeletedRequ) {
        Long id = functionDeletedRequ.getId();
        boolean b = this.removeById(id);
        if(b){
            functionApiService.deletedBatchFunctionApiByFunctionId(id);
        }
        return b;
    }

    @Override
    public Boolean deletedByMenuId(Long menuId) {
        QueryWrapper<Function> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Function::getMenuId, menuId)
                .eq(Function::getDeleted, Boolean.FALSE);
        return this.remove(queryWrapper);
    }

    @Override
    public List<Function> listByIds(List<Long> functionIds, String platformCode) {
        QueryWrapper<Function> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(Function::getId, functionIds)
                .eq(Function::getPlatformCode, platformCode)
                .eq(Function::getDeleted, Boolean.FALSE);
        return this.list(queryWrapper);
    }

}
